"""公共中间件模块

定义项目中使用的自定义中间件。
"""

import time
import logging
from django.utils.deprecation import MiddlewareMixin
from django.http import JsonResponse
from django.conf import settings
from django.core.cache import cache
from django.contrib.auth import get_user_model
from rest_framework import status

User = get_user_model()
logger = logging.getLogger('linkbook')


class RequestLoggingMiddleware(MiddlewareMixin):
    """请求日志中间件
    
    记录所有API请求的详细信息，用于调试和监控。
    """
    
    def process_request(self, request):
        """处理请求开始"""
        request.start_time = time.time()
        
        # 记录请求信息
        logger.info(
            f"Request started: {request.method} {request.get_full_path()} "
            f"from {self._get_client_ip(request)}"
        )
        
        return None
    
    def process_response(self, request, response):
        """处理请求结束"""
        if hasattr(request, 'start_time'):
            duration = time.time() - request.start_time
            
            # 记录响应信息
            logger.info(
                f"Request completed: {request.method} {request.get_full_path()} "
                f"- Status: {response.status_code} - Duration: {duration:.3f}s"
            )
        
        return response
    
    def _get_client_ip(self, request):
        """获取客户端IP地址"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip


class RateLimitMiddleware(MiddlewareMixin):
    """API限流中间件
    
    防止API被恶意调用，保护服务器资源。
    """
    
    def __init__(self, get_response):
        self.get_response = get_response
        # 默认限流配置：每分钟最多60次请求
        self.rate_limit = getattr(settings, 'API_RATE_LIMIT', 60)
        self.rate_period = getattr(settings, 'API_RATE_PERIOD', 60)  # 秒
        super().__init__(get_response)
    
    def process_request(self, request):
        """检查请求频率"""
        # 跳过非API请求
        if not request.path.startswith('/api/'):
            return None
        
        # 获取客户端标识
        client_id = self._get_client_identifier(request)
        cache_key = f"rate_limit:{client_id}"
        
        # 获取当前请求次数
        current_requests = cache.get(cache_key, 0)
        
        if current_requests >= self.rate_limit:
            return JsonResponse({
                'error': 'Rate limit exceeded',
                'message': f'Maximum {self.rate_limit} requests per {self.rate_period} seconds',
                'retry_after': self.rate_period
            }, status=status.HTTP_429_TOO_MANY_REQUESTS)
        
        # 增加请求计数
        cache.set(cache_key, current_requests + 1, self.rate_period)
        
        return None
    
    def _get_client_identifier(self, request):
        """获取客户端唯一标识"""
        # 优先使用用户ID（如果用户已认证）
        if hasattr(request, 'user') and request.user and request.user.is_authenticated:
            return f"user:{request.user.id}"
        
        # 使用IP地址
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        
        return f"ip:{ip}"


class SecurityHeadersMiddleware(MiddlewareMixin):
    """安全头中间件
    
    添加安全相关的HTTP头，提高应用安全性。
    """
    
    def process_response(self, request, response):
        """添加安全头"""
        # 防止点击劫持
        response['X-Frame-Options'] = 'DENY'
        
        # 防止MIME类型嗅探
        response['X-Content-Type-Options'] = 'nosniff'
        
        # XSS保护
        response['X-XSS-Protection'] = '1; mode=block'
        
        # 引用策略
        response['Referrer-Policy'] = 'strict-origin-when-cross-origin'
        
        # 内容安全策略（仅在生产环境）
        if not settings.DEBUG:
            response['Content-Security-Policy'] = (
                "default-src 'self'; "
                "script-src 'self' 'unsafe-inline'; "
                "style-src 'self' 'unsafe-inline'; "
                "img-src 'self' data: https:; "
                "font-src 'self' https:; "
                "connect-src 'self';"
            )
        
        # 权限策略
        response['Permissions-Policy'] = (
            "geolocation=(), "
            "microphone=(), "
            "camera=()"
        )
        
        return response


class CORSMiddleware(MiddlewareMixin):
    """CORS中间件
    
    处理跨域请求，允许前端应用访问API。
    """
    
    def __init__(self, get_response):
        self.get_response = get_response
        self.allowed_origins = getattr(settings, 'CORS_ALLOWED_ORIGINS', [])
        self.allow_credentials = getattr(settings, 'CORS_ALLOW_CREDENTIALS', True)
        super().__init__(get_response)
    
    def process_request(self, request):
        """处理预检请求"""
        if request.method == 'OPTIONS':
            response = JsonResponse({})
            return self._add_cors_headers(request, response)
        return None
    
    def process_response(self, request, response):
        """添加CORS头"""
        return self._add_cors_headers(request, response)
    
    def _add_cors_headers(self, request, response):
        """添加CORS相关头"""
        origin = request.META.get('HTTP_ORIGIN')
        
        # 检查来源是否被允许
        if origin and (not self.allowed_origins or origin in self.allowed_origins):
            response['Access-Control-Allow-Origin'] = origin
        
        if self.allow_credentials:
            response['Access-Control-Allow-Credentials'] = 'true'
        
        response['Access-Control-Allow-Methods'] = 'GET, POST, PUT, PATCH, DELETE, OPTIONS'
        response['Access-Control-Allow-Headers'] = (
            'Accept, Accept-Language, Content-Language, Content-Type, '
            'Authorization, X-Requested-With'
        )
        response['Access-Control-Max-Age'] = '86400'  # 24小时
        
        return response


class UserActivityMiddleware(MiddlewareMixin):
    """用户活动中间件
    
    更新用户的最后活动时间。
    """
    
    def process_response(self, request, response):
        """更新用户活动时间"""
        if (request.user and 
            request.user.is_authenticated and 
            request.path.startswith('/api/')):
            
            # 使用缓存避免频繁数据库更新
            cache_key = f"user_activity:{request.user.id}"
            last_update = cache.get(cache_key)
            
            if not last_update:
                # 每5分钟最多更新一次
                from django.utils import timezone
                User.objects.filter(id=request.user.id).update(
                    last_activity=timezone.now()
                )
                cache.set(cache_key, True, 300)  # 5分钟缓存
        
        return response


class HealthCheckMiddleware(MiddlewareMixin):
    """健康检查中间件
    
    提供简单的健康检查端点。
    """
    
    def process_request(self, request):
        """处理健康检查请求"""
        if request.path == '/health/':
            return JsonResponse({
                'status': 'healthy',
                'timestamp': time.time(),
                'version': getattr(settings, 'VERSION', '1.0.0')
            })
        
        return None


class ErrorHandlingMiddleware(MiddlewareMixin):
    """错误处理中间件
    
    统一处理未捕获的异常。
    """
    
    def process_exception(self, request, exception):
        """处理异常"""
        # 记录异常
        logger.error(
            f"Unhandled exception in {request.method} {request.get_full_path()}: "
            f"{type(exception).__name__}: {str(exception)}",
            exc_info=True
        )
        
        # 在生产环境返回通用错误信息
        if not settings.DEBUG:
            return JsonResponse({
                'error': 'Internal server error',
                'message': 'An unexpected error occurred. Please try again later.',
                'code': 'INTERNAL_ERROR'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
        # 开发环境让Django处理异常
        return None